﻿using Avalonia.Controls;
using LightCAD.Core;
using LightCAD.Core.Elements;
using LightCAD.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.Xml.Linq;
using static LightCAD.Core.Elements.LcPolyLine;

namespace LightCAD.Drawing.Actions
{

    public class RectangAction : ElementAction
    {

        public static string CommandName;
        public static LcCreateMethod[] CreateMethods;

        internal static void Initilize()
        {
            ElementActions.Rectang = new RectangAction();
            LcDocument.ElementActions.Add(BuiltinElementType.Rectang, ElementActions.Rectang);

        }

        private InElementsInputer InElementsInputer { get; set; }
        private ElementSetInputer ElementInputers { get; set; }
        private ElementInputer ElementInputer { get; set; }
        private CmdTextInputer CmdTextInputer { get; set; }
        private PointInputer PointInputer { get; set; }
        private RectangAction() { }


        public RectangAction(IDocumentEditor docEditor) : base(docEditor)
        {
            this.commandCtrl.WriteInfo("命令：RECTANG");
        }


        private LcCreateMethod GetMethod(string method)
        {
            if (method == null)
                return SetCurMethod(CreateMethods, 0);

            int getted = CreateMethods.ToList().FindIndex(m => m.Name == method);
            if (getted == -1)
                return SetCurMethod(CreateMethods, 0);
            else
                return SetCurMethod(CreateMethods, getted);
        }






        static RectangAction()
        {          
            CommandName = "RECTANG";
            CreateMethods = new LcCreateMethod[2];
            

            CreateMethods[0] = new LcCreateMethod()
            {
                Name = "CreateRectangBOP",
                Description = "打一点前命令",
                Steps = new LcCreateStep[]
              {
                    new LcCreateStep { Name=  "Step0", Options= "RECTANG 指定第一个角点获[倒角(C)/标高（E）/圆角（F）/厚度（T）宽度（W）]:" },

                    new LcCreateStep { Name=  "C_Step0", Options= "RECTANG 指定矩形的第一个倒角距离:" },
                    new LcCreateStep { Name=  "C_Step1", Options= "RECTANG 指定矩形的第二个倒角距离:" },

                    new LcCreateStep { Name=  "E_Step0", Options= "RECTANG 指定矩形的标高:" },

                    new LcCreateStep { Name=  "F_Step0", Options= "RECTANG 指定矩形的圆角半径:" },

                    new LcCreateStep { Name=  "T_Step0", Options= "RECTANG 指定矩形的厚度:" },

                    new LcCreateStep { Name=  "W_Step0", Options= "RECTANG 指定矩形的线宽:" },

              }
            };


            

            CreateMethods[1] = new LcCreateMethod()
            {
                Name = "CreateRectangAOP",
                Description = "打一点后命令",
                Steps = new LcCreateStep[]
                {
                    new LcCreateStep { Name=  "Step1", Options= "RECTANG 指定另一个角点或[面积(A)/尺寸(D)/旋转(R)]:" },

                    new LcCreateStep { Name=  "A_Step0", Options= "RECTANG 输入以当前单位计算的矩形面积:" },
                    new LcCreateStep { Name=  "A_Step1", Options= "RECTANG 计算矩形标注时依据[长度（L）宽度（W）]:" },
                    new LcCreateStep { Name=  "A_Step2", Options= "RECTANG 输入矩形长度:" },
                    new LcCreateStep { Name=  "A_Step3", Options= "RECTANG 输入矩形宽度:" },

                    new LcCreateStep { Name=  "D_Step0", Options= "RECTANG 指定矩形的长度:" },
                    new LcCreateStep { Name=  "D_Step1", Options= "RECTANG 指定矩形的宽度:" },

                    new LcCreateStep { Name=  "R_Step0", Options= "RECTANG 指定旋转角度或[拾取点(P)]:" },
                    new LcCreateStep { Name=  "R_Step1", Options= "RECTANG 指定第一个点:" },
                    new LcCreateStep { Name=  "R_Step2", Options= "RECTANG 指定第二个点:" },
                }
            };


        }


      
        private List<Vector2> Points { get; set; }
        private Vector2? FirstPoint { get; set; }
        private Vector2? SecondPoint { get; set; }
        private List<Curve2d> Segments { get; set; }


        private double Area { get; set; }
        private double Width { get; set; }
        private double Length { get; set; }

        private PointInputer Inputer { get; set; }
        private string _methodName;
        private string _methodArg;



        public async void ExecCreate(string[] args = null)
        {
            var method = "CreatePolygon";
            if (args != null && args.Length > 0)
            {
                method = args[0];
            }
            
            this.Inputer = new PointInputer(this.docEditor);
            this.StartCreating();


        #region Method_CreateRectangBOP_Step0
        Method_CreateRectangBOP_Step0:


            var curMethod = this.GetMethod(method);
            
            curMethod = this.SetCurMethod(CreateMethods, 0);
            
            var BOP_step0 = SetCurStep(curMethod, 0);
            _methodName = curMethod.Name;

            var BOP_result0 = await Inputer.Execute(BOP_step0.Options);
            if (Inputer.isCancelled) { this.Cancel(); return; }

            if (BOP_result0.ValueX != null)
            {
                FirstPoint = (Vector2)BOP_result0.ValueX;
                goto Method_CreateRectangAOP_Step0;
            }

            if (BOP_result0.ValueX == null)
            {
                if (Inputer.isCancelled) { this.Cancel(); return; }
                if (BOP_result0.Option.ToUpper() == "C")
                {
                    //后期补
                    return;
                }

                if (BOP_result0.Option.ToUpper() == "E")
                {



                    goto Method_CreateRectangAOP_Step0;
                }

                if (BOP_result0.Option.ToUpper() == "F")
                {



                    goto Method_CreateRectangAOP_Step0;
                }

                if (BOP_result0.Option.ToUpper() == "T")
                {



                    goto Method_CreateRectangAOP_Step0;
                }

                if (BOP_result0.Option.ToUpper() == "W")
                {



                    goto Method_CreateRectangAOP_Step0;
                }

                if (BOP_result0.Option.ToUpper() != "C" || BOP_result0.Option.ToUpper() != "E" || BOP_result0.Option.ToUpper() != "F" || BOP_result0.Option.ToUpper() != "T" || BOP_result0.Option.ToUpper() != "W")
                {
                    return;

                }
            }

        #endregion



        #region Method_CreateRectangAOP_Step0
        Method_CreateRectangAOP_Step0:

            curMethod = this.SetCurMethod(CreateMethods, 1);
            _methodName = curMethod.Name;
            var AOP_step0 = SetCurStep(curMethod, 0);
            var AOP_result0 = await Inputer.Execute(AOP_step0.Options);
            if (Inputer.isCancelled) { this.Cancel(); return; }

            if (AOP_result0.ValueX != null)
            {
                SecondPoint = (Vector2)AOP_result0.ValueX;
                Segments = TPRectang(FirstPoint, SecondPoint);               
                goto End;
            }

            if (AOP_result0.ValueX == null)
            {
                if (Inputer.isCancelled) { this.Cancel(); return; }
                if (AOP_result0.Option.ToUpper() == "A")
                {
                    var AOP_step1 = SetCurStep(curMethod, 1);
                    var AOP_result1 = await Inputer.Execute(AOP_step1.Options);
                    if (Inputer.isCancelled) { this.Cancel(); return; }
                    if (AOP_result1.Option != null && double.TryParse(AOP_result1.Option, out double optionValue1))
                    {
                        Area = optionValue1;
                        var AOP_step2 = SetCurStep(curMethod, 2);
                        var AOP_result2 = await Inputer.Execute(AOP_step2.Options);
                        if (Inputer.isCancelled) { this.Cancel(); return; }
                        if (AOP_result2.Option.ToUpper() == "L")
                        {
                            var AOP_step3 = SetCurStep(curMethod, 3);
                            var AOP_result3 = await Inputer.Execute(AOP_step3.Options);
                            if (Inputer.isCancelled) { this.Cancel(); return; }
                            if (AOP_result3.Option != null && double.TryParse(AOP_result3.Option, out double optionValue3))
                            {
                                Length = optionValue3;
                                Segments = ALRectang(FirstPoint, Area, Length);
                                goto End;
                            }
                            else { return; }
                        }


                        if (AOP_result2.Option.ToUpper() == "W")
                        {
                            var AOP_step4 = SetCurStep(curMethod, 4);
                            var AOP_result4 = await Inputer.Execute(AOP_step4.Options);
                            if (Inputer.isCancelled) { this.Cancel(); return; }
                            if (AOP_result4.Option != null && double.TryParse(AOP_result4.Option, out double optionValue4))
                            {
                                Width = optionValue4;
                                Segments = ALRectang(FirstPoint, Area, Width);
                                goto End;
                            }
                            else { return; }
                        }
                        else { return; }

                    }
                    else { return; }
                }

                if (AOP_result0.Option.ToUpper() == "D")
                {
                    var AOP_step5 = SetCurStep(curMethod, 5);
                    var AOP_result5 = await Inputer.Execute(AOP_step5.Options);
                    if (Inputer.isCancelled) { this.Cancel(); return; }
                    if (AOP_result5.Option != null && double.TryParse(AOP_result5.Option, out double optionValue5))
                    {
                        Length = optionValue5;
                        var AOP_step6 = SetCurStep(curMethod, 6);
                        var AOP_result6 = await Inputer.Execute(AOP_step6.Options);
                        if (Inputer.isCancelled) { this.Cancel(); return; }
                        if (AOP_result5.Option != null && double.TryParse(AOP_result6.Option, out double optionValue6))
                        {
                            Width = optionValue6;
                            Segments = LWRectang(FirstPoint, Length, Width);
                            goto End;
                        }
                        else { return; }
                    }
                    else { return; }

                }

                if (AOP_result0.Option.ToUpper() == "R")
                {


                    return;//暂时

                }

                if (AOP_result0.Option.ToUpper() != "A" || AOP_result0.Option.ToUpper() != "D" || AOP_result0.Option.ToUpper() != "R")
                {
                    return;

                }




            }

        #endregion

        End:
            CreateRectang(Segments);
            this.Inputer = null;
            this.EndCreating();
        }

        




        private void CreateRectang(List<Curve2d> seg)   //最终渲染
        {
            if (seg == null || seg.Count != 4)
            {
                // 如果线段列表为空或线段数量不为4，则无法创建矩形
                return;
            }
            var doc = this.docRt.Document;
            DocumentManager.CurrentRecorder.BeginAction("PolyLine");
            var PolyLine = doc.CreateObject<LcPolyLine>();
            PolyLine.IsClosed = true;

            PolyLine.Curve2ds = seg;

            doc.ModelSpace.InsertElement(PolyLine);
            this.docRt.Action.ClearSelects();
            DocumentManager.CurrentRecorder.EndAction();

        }    
       
        public override void DrawAuxLines(SKCanvas canvas)    //实时渲染
        {
            if (this.FirstPoint != null)
            {
                var mp = this.vportRt.PointerMovedPosition.ToVector2d();
                var secPoint = this.vportRt.ConvertScrToWcs(mp);
                Vector2 topLeft = new Vector2(Math.Min(this.FirstPoint.X, secPoint.X), Math.Max(this.FirstPoint.Y, secPoint.Y));
                Vector2 bottomRight = new Vector2(Math.Max(this.FirstPoint.X, secPoint.X), Math.Min(this.FirstPoint.Y, secPoint.Y));
                Vector2 topRight = new Vector2(bottomRight.X, topLeft.Y);
                Vector2 bottomLeft = new Vector2(topLeft.X, bottomRight.Y);

                DrawAuxLine(canvas, topLeft, topRight, new SKPaint { Color = this.vportRt.GetAuxColorValue(), IsStroke = true });
                DrawAuxLine(canvas, topRight, bottomRight, new SKPaint { Color = this.vportRt.GetAuxColorValue(), IsStroke = true });
                DrawAuxLine(canvas, bottomRight, bottomLeft, new SKPaint { Color = this.vportRt.GetAuxColorValue(), IsStroke = true });
                DrawAuxLine(canvas, bottomLeft, topLeft, new SKPaint { Color = this.vportRt.GetAuxColorValue(), IsStroke = true });
            }
        }

        private void DrawAuxLine(SKCanvas canvas, Vector2 p0, Vector2 p1, SKPaint sKPaint)   //实时渲染
        {
            var sk_pre = this.vportRt.ConvertWcsToScr(p0).ToSKPoint();
            var sk_p = this.vportRt.ConvertWcsToScr(p1).ToSKPoint();
            //辅助元素的颜色 
            canvas.DrawLine(sk_pre, sk_p, sKPaint);
            //辅助曲线的颜色，包括辅助长度，辅助角度等

        }



        public static List<Curve2d> ALRectang(Vector2 firstpoint, double area,  double length)  //已知面积后根据长度生成边
        {
            double width = area / length + area % length;

            //生成四个点坐标（bottomLeft=Fpoint;   bottomRight.x=Fpoint.x+Long,bottomRight.y=Fpoint.y;  topLeft.x=Fpoint.x,topLeft.y=Fpoint.y+Long2;    topRight.x=Fpoint.x+long,topRight.y=Fpoint.y+Long2)

            Vector2 bottomLeft = firstpoint;
            Vector2 bottomRight = new Vector2(bottomLeft.X + length, bottomLeft.Y);
            Vector2 topLeft = new Vector2(bottomLeft.X, bottomLeft.Y + width);
            Vector2 topRight = new Vector2(bottomRight.X, topLeft.Y);




            // Create rectangle segments
            List<Curve2d> segments = new List<Curve2d>();
            Line2d seg1 = new Line2d();
            seg1.Start = topLeft;
            seg1.End = topRight;
            segments.Add(seg1);

            Line2d seg2 = new Line2d();
            seg2.Start = topRight;
            seg2.End = bottomRight;
            segments.Add(seg2);

            Line2d seg3 = new Line2d();
            seg3.Start = bottomRight;
            seg3.End = bottomLeft;
            segments.Add(seg3);

            Line2d seg4 = new Line2d();
            seg4.Start = bottomLeft;
            seg4.End = topLeft;
            segments.Add(seg4);


            return segments;

        }



        public static List<Curve2d> AWRectang(Vector2 firstpoint, double area, double width)  //已知面积后根据宽度生成边
        {
            double length = area / width + area % width;

            //生成四个点坐标（bottomLeft=Fpoint;   bottomRight.x=Fpoint.x+Long,bottomRight.y=Fpoint.y;  topLeft.x=Fpoint.x,topLeft.y=Fpoint.y+Long2;    topRight.x=Fpoint.x+long,topRight.y=Fpoint.y+Long2)

            Vector2 bottomLeft = firstpoint;
            Vector2 bottomRight = new Vector2(bottomLeft.X + length, bottomLeft.Y);
            Vector2 topLeft = new Vector2(bottomLeft.X, bottomLeft.Y + width);
            Vector2 topRight = new Vector2(bottomRight.X, topLeft.Y);

            // Create rectangle segments
            List<Curve2d> segments = new List<Curve2d>();
            Line2d seg1 = new Line2d();
            seg1.Start = topLeft;
            seg1.End = topRight;
            segments.Add(seg1);

            Line2d seg2 = new Line2d();
            seg2.Start = topRight;
            seg2.End = bottomRight;
            segments.Add(seg2);

            Line2d seg3 = new Line2d();
            seg3.Start = bottomRight;
            seg3.End = bottomLeft;
            segments.Add(seg3);

            Line2d seg4 = new Line2d();
            seg4.Start = bottomLeft;
            seg4.End = topLeft;
            segments.Add(seg4);

            return segments;

        }



        public static List<Curve2d> TPRectang(Vector2 firstpoint, Vector2 secondpoint)       //两点生成矩形
        {
            // Calculate rectangle vertices
            Vector2 topLeft = new Vector2(Math.Min(firstpoint.X, secondpoint.X), Math.Max(firstpoint.Y, secondpoint.Y));
            Vector2 bottomRight = new Vector2(Math.Max(firstpoint.X, secondpoint.X), Math.Min(firstpoint.Y, secondpoint.Y));
            Vector2 topRight = new Vector2(bottomRight.X, topLeft.Y);
            Vector2 bottomLeft = new Vector2(topLeft.X, bottomRight.Y);

            // Create rectangle segments
            List<Curve2d> segments = new List<Curve2d>();
            Line2d seg1 = new Line2d();
            seg1.Start = topLeft;
            seg1.End = topRight;
            segments.Add(seg1);

            Line2d seg2 = new Line2d();
            seg2.Start = topRight;
            seg2.End = bottomRight;
            segments.Add(seg2);

            Line2d seg3 = new Line2d();
            seg3.Start = bottomRight;
            seg3.End = bottomLeft;
            segments.Add(seg3);

            Line2d seg4 = new Line2d();
            seg4.Start = bottomLeft;
            seg4.End = topLeft;
            segments.Add(seg4);

            return segments;
        }


        public static List<Curve2d> LWRectang(Vector2 firstpoint, double length, double width)    //尺寸画矩形
        {
            //生成四个点坐标（bottomLeft=Fpoint;   bottomRight.x=Fpoint.x+Long,bottomRight.y=Fpoint.y;  topLeft.x=Fpoint.x,topLeft.y=Fpoint.y+Long2;    topRight.x=Fpoint.x+long,topRight.y=Fpoint.y+Long2)

            Vector2 bottomLeft = firstpoint;
            Vector2 bottomRight = new Vector2(bottomLeft.X + length, bottomLeft.Y);
            Vector2 topLeft = new Vector2(bottomLeft.X, bottomLeft.Y + width);
            Vector2 topRight = new Vector2(bottomRight.X, topLeft.Y);

            // Create rectangle segments
            List<Curve2d> segments = new List<Curve2d>();
            Line2d seg1 = new Line2d();
            seg1.Start = topLeft;
            seg1.End = topRight;
            segments.Add(seg1);

            Line2d seg2 = new Line2d();
            seg2.Start = topRight;
            seg2.End = bottomRight;
            segments.Add(seg2);

            Line2d seg3 = new Line2d();
            seg3.Start = bottomRight;
            seg3.End = bottomLeft;
            segments.Add(seg3);

            Line2d seg4 = new Line2d();
            seg4.Start = bottomLeft;
            seg4.End = topLeft;
            segments.Add(seg4);

            return segments;
        }





    }
}


